﻿/**
 * Author: Rick van Rijn(RVR)
 * Date: 26-3-2012
 * Groep: 3
 * Versiebeheer:
 * Version 1.0 Algorithm created RVR
 * Version 1.1 Little bug fixed RVR
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms;

namespace KentekenHerkenning
{
    class MeanHSVAlgorithm
    {
        //Public values
        public static double Hue;
        public static double Saturation;

        public static Bitmap DoAlgorithm(System.Drawing.Bitmap sourceImage)
        {
            //copy Bitmap and lockbits for alternation
            Bitmap renderedImage = new Bitmap(sourceImage);
            Rectangle rect = new Rectangle(0, 0, renderedImage.Width, renderedImage.Height);
            BitmapData returnImageDate = renderedImage.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

            //create safe pointer
            IntPtr pointer = returnImageDate.Scan0;
            int Size = Math.Abs(returnImageDate.Stride) * renderedImage.Height;

            //arrays of Byte type for BitmapData
            byte[] invert = new Byte[Size];
            byte[] temp = new Byte[Size];

            //copy pointer data to byte array:: invert
            System.Runtime.InteropServices.Marshal.Copy(pointer, invert, 0, Size);

            //get total of pixels and calculate the const value
            uint pixels = (uint)renderedImage.Height * (uint)renderedImage.Width;
            decimal Const = 255 / (decimal)pixels;

            //initialise hsv variables
            double hue = 0.0;
            double satur = 0.0;
            double value = 0.0;

            //Run for loop to get all hsv values
            for (int i = 0; i < Size; i += 4)
            {
                //calculate hsv values
                double h, s, v;
                convertToHSV(Color.FromArgb((Int32)invert[i + 2], (Int32)invert[i + 1], (Int32)invert[i]), out h, out s, out v);
                
                //add values to local variables
                hue += h;
                satur += s;
                value += v;
            }

            //to calculate the average hue, saturation en value and store them in the same variable
            hue = hue / pixels;
            satur = satur / pixels;
            value = value / pixels;

            //write value of local variable to the public variant
            Hue = hue;
            Saturation = satur;

            //copy invert array to BitmapData
            System.Runtime.InteropServices.Marshal.Copy(invert, 0, pointer, Size);
            //unlock Bitmap
            renderedImage.UnlockBits(returnImageDate);
            //Return Bitmap
            return renderedImage;
        }


        //Function to calculate HSV value of one pixel
        public static void convertToHSV(Color color, out double hue, out double saturation, out double value)
        {
            //get the maximum of the three RGB values
            int max = Math.Max(color.R, Math.Max(color.G, color.B));

            //get the minimum of the three RGB values
            int min = Math.Min(color.R, Math.Min(color.G, color.B));

            //gets the Hue value
            hue = color.GetHue();

            //caluculate saturation
            saturation = (max == 0) ? 0 : 1d - (1d * min / max);

            //calculate value
            value = max / 255d;

        }

    }
}